// Copyright 2019 The rhyme_lph Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// d [author] rhyme_lph
// E [email]  rhymelph@gmail.com
// F [github] https://github.com/rhymelph

import 'dart:async';

import 'package:base_plugin/base_plugin.dart';
import 'package:dio/src/response.dart';
import 'package:finance_app/generated/l10n.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/entities/business_contact_entity.dart';
import 'package:finance_app/src/http_service/http_contact_service.dart';
import 'package:finance_app/src/mixin/check_plan_mixin.dart';
import 'package:finance_app/src/mixin/contacts_sort_mixin.dart';
import 'package:finance_app/src/mixin/filter_contact_sort_mixin.dart';
import 'package:finance_app/src/mixin/format_group_map_mixin.dart';
import 'package:finance_app/src/mixin/refresh_mixin.dart';
import 'package:finance_app/src/mixin/search_data_list_mixin.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/reg_exp_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class MainBusinessContactProvider extends BaseProvider<List<BusinessContactEntity>>
    with
        SearchDataListMixin,
        FilterContactSortMixin,
        ContactsSortMixin,
        RefreshMixin<List<BusinessContactEntity>, List<BusinessContactEntity>>,
        FormatGroupMapLocalMixin<BusinessContactEntity>,
        CheckPlanMixin {
  List<String> menuList = ['Import', 'Delete'];

  bool buttonBarIsUp = true;

  void handleScrollUpdate(ScrollController controller) {
    if (controller.position.userScrollDirection == ScrollDirection.reverse && buttonBarIsUp == true) {
      //向下滑动
      buttonBarIsUp = false;
      update();
    }
    if (controller.position.userScrollDirection == ScrollDirection.forward && buttonBarIsUp == false) {
      buttonBarIsUp = true;
      update();
    }
  }

  ScrollController controller = ScrollController();

  @override
  void initState() {
    super.initState();
    controller.addListener(() {
      handleScrollUpdate(controller);
    });
  }

  void onAddBusiness() async {
    unFocus();
    await Routes.navigateTo(RouterGenProviders.businessContactProfilePage, params: {
      'name': searchController.text,
    });
  }

  @override
  Future get dataFuture => HttpContactService.contactList(1);

  void unFocus() {
    searchFocusNode.unfocus();
  }

  void onSelectMenu(String value) {
    unFocus();
    switch (value) {
      case 'Import':
        Routes.navigateTo(RouterGenProviders.importBusinessContactPage);
        break;
      case 'Delete':
        onDelete();
        break;
    }
  }

  void onDelete() {
    if (isPlanExpired()) return;

    unFocus();
    Routes.navigateTo(RouterGenProviders.deleteBusinessContactPage);
  }

  void onNavAdd() async {
    if (isPlanExpired()) return;
    unFocus();
    await Routes.navigateTo(RouterGenProviders.businessContactProfilePage);
  }

  @override
  FutureOr<List<BusinessContactEntity>> transformData(List<BusinessContactEntity> d, bool isCache) {
    contactToMap(d);
    return d;
  }

  void contactToMap(List<BusinessContactEntity> contacts) {
    groupMap.clear();
    if (currentSelectSortContact == S.current.alphabetical) {
      sortGroupToMap(contacts,
          sort: (a, b) => sortNameFirst(a, b, (t) => t.name),
          filter: _onFilter,
          group: (a) => groupFirstName(a, (t) => t.name, '*'),
          itemBefore: (map, b) => favoriteBefore(map, b, (b) => b.isFavorite));
      if (groupMap['Favourites'] != null && groupMap['Favourites'].length == 0) {
        groupMap.remove('Favourites');
      }
    } else if (currentSelectSortContact == S.current.recently_transacted) {
      sortGroupToMap(contacts,
          sort: (a, b) => sortIssuesAt(a, b, (t) => t.lastTransactionAt, (t) => t.id),
          filter: _onFilter,
          group: (a) => groupMonth(a, (t) => t.lastTransactionAt));
    } else {
      sortGroupToMap(contacts,
          sort: (a, b) => sortPayAmount(a, b, (t) => t.isFavorite, (t) => (t.receivingAmount ?? 0.0) - (t.payingAmount ?? 0.0)), group: groupOnly);
    }
  }

  void onSelectBusinessContact(BusinessContactEntity data) {
    unFocus();
    Routes.navigateTo(RouterGenProviders.businessContactDetailPage, params: {'data': data});
  }

  @override
  List<BusinessContactEntity> get dataList => data;

  @override
  List<BusinessContactEntity> getFromRequestResult(Response<dynamic> result, bool isRefresh) {
    List<BusinessContactEntity> resultData = getEntityFromResult<List<BusinessContactEntity>>(result);
    contactToMap(resultData);
    return resultData;
  }

  @override
  Future get refreshFuture => dataFuture;

  bool _onFilter(BusinessContactEntity a) {
    bool isNotFilter = false;
    //先判断
    if (RegExpUtils.getSearchRegExp(searchController.text).hasMatch(a.name)) {
      List<bool> hasTrueList = [];
      if (currentSelectFilterList.length == 0) {
        hasTrueList.add(true);
      } else {
        if (currentSelectFilterList.contains('Net Incoming')) {
          //净收入
          hasTrueList.add(a.receivingAmount > 0 && a.payingAmount == 0);
        }
        if (currentSelectFilterList.contains('Net Outgoing')) {
          //净支出
          hasTrueList.add(a.payingAmount > 0 && a.receivingAmount == 0);
        }
        if (currentSelectFilterList.contains('Overdue Transactions')) {
          hasTrueList.add(a.isOverdue == 1);
        }
        if (currentSelectFilterList.contains('Client')) {
          hasTrueList.add(a.isClient == 1);
        }
        if (currentSelectFilterList.contains('Supplier')) {
          hasTrueList.add(a.isSupplier == 1);
        }
      }
      isNotFilter = hasTrueList.contains(true);
    }
    return isNotFilter;
  }

  @override
  void searchRefreshData(data) {
    contactToMap(dataList);
    update();
  }

  @override
  void sortUpdate() {
    contactToMap(dataList);
  }

  @override
  void onRequestRefresh() {
    contactToMap(dataList);
  }

  void onClickStar(BusinessContactEntity e) async {
    bool isSuccess = false;
    await post(HttpContactService.updateContact(e.id, is_favorite: e.isFavorite == 1 ? 0 : 1), autoHandler: AutoHandler.Toast, loadingTip: S.current.loading,
        onSuccess: (result) {
      isSuccess = true;
    });
    if (isSuccess == true) {
      e.isFavorite = e.isFavorite == 1 ? 0 : 1;
      contactToMap(dataList);
      update();
    }
  }

  @override
  bool get isShowNet => false;

  void updateContact(BusinessContactEntity entity) {
    final updateData = dataList.firstWhere((element) => element.id == entity.id, orElse: () => null);
    if (updateData != null) {
      updateData.fromJson(entity.toJson());
      contactToMap(dataList);
      update();
    } else {
      dataList.add(entity);
      contactToMap(dataList);
      update();
    }
  }

  void onDeleteContact(int id) {
    data.removeWhere((element) => element.id == id);
    contactToMap(dataList);
    update();
  }
}
